import { useCallback, useEffect, useRef, useState } from 'react';
import type {
  CommunicationCleanup,
  UseMicroAppErrorOptions,
  UseMicroAppErrorReturn,
} from '../types';

/**
 * useMicroAppError Hook
 *
 * 功能特性：
 * - 管理错误状态 (hasError, error)
 * - 提供错误处理 (retry, clearError)
 * - 提供错误监听 (onError)
 * - 支持自动重试
 * - 处理重试逻辑
 * - 重试计数和延迟控制
 */
export function useMicroAppError(
  options: UseMicroAppErrorOptions = {},
): UseMicroAppErrorReturn {
  const {
    autoRetry = false,
    retryCount = 3,
    retryDelay = 1000,
    onError,
    onRetry,
  } = options;

  // 状态管理
  const [hasError, setHasError] = useState(false);
  const [error, setError] = useState<Error | null>(null);
  const [currentRetryCount, setCurrentRetryCount] = useState(0);

  // 引用
  const retryTimerRef = useRef<NodeJS.Timeout | null>(null);
  const errorListenersRef = useRef<Array<(error: Error) => void>>([]);

  // 清理定时器
  const clearRetryTimer = useCallback(() => {
    if (retryTimerRef.current) {
      clearTimeout(retryTimerRef.current);
      retryTimerRef.current = null;
    }
  }, []);

  // 重试
  const retry = useCallback(() => {
    console.log('重试微应用操作');

    // 清理定时器
    clearRetryTimer();

    // 增加重试计数
    setCurrentRetryCount((prev) => prev + 1);

    // 清除错误状态
    setHasError(false);
    setError(null);

    // 调用重试回调
    if (onRetry) {
      try {
        onRetry();
      } catch (retryError) {
        console.error('重试回调执行失败:', retryError);
        // 直接设置错误状态，避免循环依赖
        setError(retryError as Error);
        setHasError(true);
      }
    }
  }, [onRetry, clearRetryTimer]);

  // 设置错误
  const setErrorState = useCallback(
    (newError: Error) => {
      console.error('微应用错误:', newError);

      setError(newError);
      setHasError(true);

      // 触发错误监听器
      errorListenersRef.current.forEach((listener) => {
        try {
          listener(newError);
        } catch (listenerError) {
          console.error('错误监听器执行失败:', listenerError);
        }
      });

      // 调用外部错误回调
      if (onError) {
        try {
          onError(newError);
        } catch (callbackError) {
          console.error('错误回调执行失败:', callbackError);
        }
      }

      // 自动重试逻辑
      if (autoRetry && currentRetryCount < retryCount) {
        console.log(`自动重试中... (${currentRetryCount + 1}/${retryCount})`);

        retryTimerRef.current = setTimeout(() => {
          retry();
        }, retryDelay);
      }
    },
    [autoRetry, retryCount, retryDelay, currentRetryCount, onError],
  );

  // 清除错误
  const clearError = useCallback(() => {
    console.log('清除微应用错误状态');

    // 清理定时器
    clearRetryTimer();

    // 重置状态
    setHasError(false);
    setError(null);
    setCurrentRetryCount(0);
  }, [clearRetryTimer]);

  // 添加错误监听器
  const onErrorListener = useCallback(
    (callback: (error: Error) => void): CommunicationCleanup => {
      console.log('添加错误监听器');

      errorListenersRef.current.push(callback);

      // 返回清理函数
      return () => {
        console.log('移除错误监听器');
        const index = errorListenersRef.current.indexOf(callback);
        if (index > -1) {
          errorListenersRef.current.splice(index, 1);
        }
      };
    },
    [],
  );

  // 手动触发错误（用于测试或外部错误处理）
  const triggerError = useCallback(
    (newError: Error) => {
      setErrorState(newError);
    },
    [setErrorState],
  );

  // 检查是否可以重试
  const canRetry = useCallback(() => {
    return currentRetryCount < retryCount;
  }, [currentRetryCount, retryCount]);

  // 获取重试信息
  const getRetryInfo = useCallback(() => {
    return {
      currentRetryCount,
      maxRetryCount: retryCount,
      canRetry: canRetry(),
      nextRetryDelay: retryDelay,
    };
  }, [currentRetryCount, retryCount, retryDelay, canRetry]);

  // 组件卸载时清理
  useEffect(() => {
    return () => {
      console.log('清理错误处理器');
      clearRetryTimer();
      errorListenersRef.current = [];
    };
  }, [clearRetryTimer]);

  // 暴露内部方法（用于调试）
  const debugMethods = {
    triggerError,
    canRetry,
    getRetryInfo,
  };

  return {
    // 错误状态
    hasError,
    error,

    // 错误处理
    retry,
    clearError,

    // 错误监听
    onError: onErrorListener,

    // 调试方法（开发环境）
    ...(process.env.NODE_ENV === 'development' && { debug: debugMethods }),
  };
}
